package com.tencreat.service.account.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tencreat.common.core.HttpResult;
import com.tencreat.common.core.domain.entity.SysUser;
import com.tencreat.common.core.domain.model.LoginUser;
import com.tencreat.common.core.domain.model.ReqIdParam;
import com.tencreat.common.core.domain.model.ReqIdsParam;
import com.tencreat.common.core.domain.model.ReqPageParam;
import com.tencreat.common.core.service.TokenService;
import com.tencreat.common.enums.*;
import com.tencreat.common.enums.mall.AllEnum;
import com.tencreat.common.exception.CustomException;
import com.tencreat.common.utils.bean.BeanUtils;
import com.tencreat.common.utils.sign.Md5Utils;
import com.tencreat.common.utils.uuid.IdUtils;
import com.tencreat.domain.account.*;
import com.tencreat.domain.account.dto.MallMessageDTO;
import com.tencreat.domain.account.dto.UpdateNewPhoneDTO;
import com.tencreat.domain.account.vo.*;
import com.tencreat.domain.mall.MallOrderGoods;
import com.tencreat.domain.mall.dto.MallMessageInformPushDTO;
import com.tencreat.mapper.account.MallUserMapper;
import com.tencreat.service.account.*;
import com.tencreat.service.mall.IMallCouponUserService;
import com.tencreat.service.mall.IMallMessageInformService;
import com.tencreat.service.mall.IMallOrderGoodsService;
import com.tencreat.service.mall.IRechargeLimitChangeService;
import com.tencreat.service.mall.impl.RechargeLimitChangeServiceImpl;
import com.tencreat.service.system.ISysMessageService;
import com.tencreat.service.system.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 用户Service业务层处理
 *
 * @author tencreat
 * @date 2021-08-13
 */
@Service
@RequiredArgsConstructor
public class MallUserServiceImpl extends ServiceImpl<MallUserMapper, MallUser> implements IMallUserService {

    private final TokenService tokenService;
    private final MallUserMapper mallUserMapper;
    private final IAccountSvipRecordService svipRecordService;
    private final ISysMessageService sysMessageService;
    private final IMallCouponUserService couponUserService;
    private final IMallOrderGoodsService mallOrderGoodsService;
    private final IMallMessageInformService mallMessageInformService;

    @Autowired
    private IMallStoreService mallStoreService;

    @Autowired
    private IRechargeLimitChangeService rechargeLimitChangeService;

    /**
     * 查询用户
     *
     * @param id 用户ID
     * @return 用户
     */
    @Override
    public MallUser selectMallUserById(ReqIdParam id) {
        return baseMapper.selectById(id.getId());
    }

    /**
     * 查询用户列表
     *
     * @param mallUser 用户
     * @return 用户
     */
    @Override
    public List<MallUser> selectMallUserList(MallUser mallUser) {
        List<MallUser> mallUsers = baseMapper.selectList(Wrappers.query(mallUser));
        mallUsers.forEach(item -> {
            //item.setIsVipDesc(item.getUserLevel().getDesc());
            if (item.getStatus() == 0) {
                item.setStatusDesc("可用");
            }
            if (item.getStatus() == 1) {
                item.setStatusDesc("禁用");
            }
            if (item.getStatus() == 2) {
                item.setStatusDesc("注销");
            }
        });
        return mallUsers;
    }

    /**
     * 新增用户
     *
     * @param mallUser 用户
     * @return 结果
     */
    @Override
    public int insertMallUser(MallUser mallUser) {
        LocalDateTime now = LocalDateTime.now();
        mallUser.setCreateTime(now);
        mallUser.setUsername(mallUser.getMobile());
        mallUser.setCreateTime(now);
        mallUser.setUpMobile(selectmobileByUuid(mallUser.getReferrerUuid()).getMobile());
        couponUserService.grantNewUserCoupon(mallUser.getUuid());
/*        if (mallUser.getUserLevel() != null && mallUser.getUserLevel().compareTo(UserType.INTERMEDIATE_MEMBER) == 0) {
            if (mallUser.getMemberType() == 1) {
                mallUser.setSVipEndTime(now.plusYears(1));
                mallUser.setStartsVipTime(LocalDateTime.now());
            }
            if (mallUser.getMemberType() == 60) {
                mallUser.setSVipEndTime(now.plusYears(60));
                mallUser.setStartsVipTime(LocalDateTime.now());
            }
        }*/
        int insert = baseMapper.insert(mallUser);
        //增加代采购额度
        rechargeLimitChangeService.change(mallUser);


        return insert;
    }

    /**
     * 修改用户
     *
     * @param mallUser 用户
     * @return 结果
     */
    @Override
    public int updateMallUser(MallUser mallUser) {
        mallUser.setUpdateTime(LocalDateTime.now());
        return baseMapper.updateById(mallUser);
    }

    /**
     * 批量删除用户
     *
     * @param ids 需要删除的用户ID
     * @return 结果
     */
    @Override
    public int deleteMallUserByIds(ReqIdsParam ids) {
        return baseMapper.deleteBatchIds(ids.getId());
    }

    /**
     * 删除用户信息
     *
     * @param id 用户ID
     * @return 结果
     */
    @Override
    public int deleteMallUserById(ReqIdParam id) {
        return baseMapper.deleteById(id.getId());
    }

    /**
     * 设置支付密码
     */
    @Override
    public HttpResult<Boolean> payPassword(String payPassword, LoginUser loginUser) {
        MallUser mallUser = lambdaQuery().eq(MallUser::getUuid, loginUser.getAccountLogin().getUuid()).one();
        mallUser.setPayPassword(payPassword);
        return HttpResult.ok(baseMapper.updateById(mallUser) > 1);
    }

    @Override
    public HttpResult<String> signOut(LoginUser loginUser) {
        tokenService.delLoginUser(loginUser.getToken());
        return HttpResult.ok("退出成功！");
    }

    /**
     * 消息推送
     *
     * @param messagePO
     * @return
     */
    @Override
    public HttpResult<Boolean> pushMessage(MallMessageDTO messagePO) {
        List<String> strings = new ArrayList<>();
        // 全部用户
        if (messagePO.getAppoint() != null && messagePO.getAppoint() == 0) {
            List<MallUser> list = list();
            for (MallUser mallUser : list) {
                strings.add(mallUser.getMobile());
            }
        }
/*        else if (messagePO.getAppoint() != null && messagePO.getAppoint() == 1) {
            // 会员用户
            List<MallUser> list = lambdaQuery().eq(MallUser::getUserLevel, UserType.INTERMEDIATE_MEMBER).list();
            for (MallUser mallUser : list) {
                strings.add(mallUser.getMobile());
            }
        }*/
        else {
            String[] split = messagePO.getPhone().split(",");
            strings = Arrays.asList(split);
        }
        if (messagePO.getAddress() != null) {

        }
        if (!messagePO.getType()) {
            for (String phone : strings) {
                sysMessageService.pushMessage(phone, messagePO.getContent());
            }
        } else {
            MallMessageInformPushDTO dto = new MallMessageInformPushDTO();
            dto.setContent(messagePO.getContent());
            dto.setTitle(messagePO.getTitle());
            dto.setType(0);
            dto.setTarget(messagePO.getAppoint());
            dto.setUserList(messagePO.getPhone());

            mallMessageInformService.push(dto);
        }

        return HttpResult.ok();
    }

    @Override
    public HttpResult<ResOpenUserInfoVO> info(LoginUser loginUser) {
        if (loginUser == null) {
            return HttpResult.ok(401, "没有token信息");
        }
        MallUser mallUser = getOne(new QueryWrapper<MallUser>().eq("uuid", loginUser.getAccountLogin().getUuid()));
        MallStore mallStore = mallStoreService.lambdaQuery().eq(MallStore::getUuid, mallUser.getUuid()).one();
        ResOpenUserInfoVO openUserInfoBO = new ResOpenUserInfoVO();
        BeanUtils.copyProperties(mallUser, openUserInfoBO);
        openUserInfoBO.setSupplierEarnings(mallUser.getFinance());
        openUserInfoBO.setStoreEarnings(mallUser.getStoreFinance());
        if (mallStore != null) {
            openUserInfoBO.setStoreId(mallStore.getId());
        }
        //查出用户代采购额度，只计算直推+间推+无限推
        BigDecimal limit = rechargeLimitChangeService.changeByUser(loginUser.getAccountLogin().getUuid());
        openUserInfoBO.setLimit(limit);

        return HttpResult.ok(openUserInfoBO);
    }

    @Override
    public HttpResult<List<MallUser>> newUser(MallUser mallUser) {
        return HttpResult.ok(baseMapper.selectNewUserList(mallUser));
    }

    @Override
    public HttpResult<List<MallUser>> pushAddressMessage(MallMessageDTO messagePO) {
        return null;
    }

    @Override
    public List<MallUser> selectOneByUuid(Long upUuid) {
        return mallUserMapper.selectOneByUuid(upUuid);
    }

    @Override
    public List<MallUser> selectALLOneByUuid() {
        return mallUserMapper.selectALLOneByUuid();
    }

    @Override
    public MallUser selectmobileByUuid(Long upUuid) {
        return mallUserMapper.selectmobileByUuid(upUuid);
    }

    @Override
    public List<MallUser> selectpartner() {
        return mallUserMapper.selectpartner();
    }

    @Override
    public List<MallUser> selectSupplier() {
        return mallUserMapper.selectSupplier();
    }

    @Override
    public List<MallUser> userList() {
        return mallUserMapper.queryAll();
    }

    @Override
    public MallUser selectmobileByid(Long uuid) {
        return mallUserMapper.selectmobileByUuid(uuid);
    }

    @Override
    public synchronized int generateUUID() {
        while (true) {
            int uuid = IdUtils.generateUUID();
            Integer oldUUID = IdUtils.idCache.get(uuid);
            if (oldUUID == null) {
                int count = lambdaQuery().eq(MallUser::getUuid, uuid).count();
                if (count == 0) {
                    IdUtils.idCache.put(uuid, uuid);
                    return uuid;
                }
            }
        }
    }

    @Override
    public List<MallUser> queryMyTeam(Long uuid) {
        return baseMapper.queryMyTeam(uuid).stream().filter(i -> !i.getUuid().equals(uuid)).collect(Collectors.toList());
    }

    @Override
    public AppMyTeamInfoVO appSelectTeam(LoginUser loginUser) {
        MallUser mallUser = lambdaQuery().eq(MallUser::getUuid, loginUser.getAccountLogin().getUuid()).one();
        BigDecimal limit = BigDecimal.ZERO;
        //查出用户代采购额度，只计算直推+间推+无限推
        limit = rechargeLimitChangeService.changeByUser(loginUser.getAccountLogin().getUuid());
        List<MallUser> list = lambdaQuery().eq(MallUser::getReferrerUuid, loginUser.getAccountLogin().getUuid()).list();
        List<AccountMyTeamVo> collect = list.stream().map(i -> {
            AccountMyTeamVo accountMyTeamVo = new AccountMyTeamVo();
            accountMyTeamVo.setUuid(i.getUuid());
            accountMyTeamVo.setAvatar(i.getAvatar());
            accountMyTeamVo.setUserName(i.getUsername());
            accountMyTeamVo.setMobile(i.getMobile());
            accountMyTeamVo.setCreateTime(i.getCreateTime());
            accountMyTeamVo.setStore(i.getStore() == null ? 0L : i.getStore());
            accountMyTeamVo.setSupplier(i.getSupplier() == null ? 0L : i.getSupplier());
            Integer count = lambdaQuery().eq(MallUser::getReferrerUuid, i.getUuid()).count();
            Integer orderCount = mallOrderGoodsService.lambdaQuery().eq(MallOrderGoods::getUuid, i.getUuid()).in(MallOrderGoods::getOrderStatus, OrderStatus.DAI_CENTXT, OrderStatus.OK).notIn(MallOrderGoods::getAftersaleStatus, AfterSaleStatus.DEL_PAY).count();
            accountMyTeamVo.setOrderCount(orderCount);
            accountMyTeamVo.setRecommendedNumber(count);
            accountMyTeamVo.setIncome(i.getFinance().add(i.getStoreFinance()) == null ? BigDecimal.ZERO : i.getFinance().add(i.getStoreFinance()));

            BigDecimal recharge = BigDecimal.ZERO;
            List<MallOrderGoods> rechargeList = mallOrderGoodsService.lambdaQuery().eq(MallOrderGoods::getUuid, i.getUuid()).eq(MallOrderGoods::getOrderType, OrderType.RECHARGE).list();
            if (rechargeList.isEmpty()) {
                accountMyTeamVo.setRecharge(recharge);
            } else {
                for (MallOrderGoods mallOrderGoods : rechargeList) {
                    recharge.add(mallOrderGoods.getPayPrice());
                }
                accountMyTeamVo.setRecharge(recharge);
            }


            return accountMyTeamVo;
        }).collect(Collectors.toList());


        // 间推用户
        List<MallUser> list1 = lambdaQuery().ne(MallUser::getReferrerUuid, mallUser.getUuid())
                .like(MallUser::getClassRelations, mallUser.getUuid()).list();
        List<AccountMyTeamVo> collect2 = list1.stream().map(i -> {
            AccountMyTeamVo accountMyTeamVo = new AccountMyTeamVo();
            accountMyTeamVo.setUuid(i.getUuid());
            accountMyTeamVo.setAvatar(i.getAvatar());
            accountMyTeamVo.setUserName(i.getUsername());
            accountMyTeamVo.setMobile(i.getMobile());
            accountMyTeamVo.setCreateTime(i.getCreateTime());
            accountMyTeamVo.setStore(i.getStore() == null ? 0L : i.getStore());
            accountMyTeamVo.setSupplier(i.getSupplier() == null ? 0L : i.getSupplier());
            Integer count = lambdaQuery().eq(MallUser::getReferrerUuid, i.getUuid()).count();
            Integer orderCount = mallOrderGoodsService.lambdaQuery().eq(MallOrderGoods::getUuid, i.getUuid()).in(MallOrderGoods::getOrderStatus, OrderStatus.DAI_CENTXT, OrderStatus.OK).count();
            accountMyTeamVo.setOrderCount(orderCount);
            accountMyTeamVo.setRecommendedNumber(count);
//            accountMyTeamVo.setRecommendedNumber(count);
            accountMyTeamVo.setIncome(i.getFinance().add(i.getStoreFinance()) == null ? BigDecimal.ZERO : i.getFinance().add(i.getStoreFinance()));

            BigDecimal recharge = BigDecimal.ZERO;
            List<MallOrderGoods> rechargeList = mallOrderGoodsService.lambdaQuery().eq(MallOrderGoods::getUuid, i.getUuid()).eq(MallOrderGoods::getOrderType, OrderType.RECHARGE).list();
            if (rechargeList.isEmpty()) {
                accountMyTeamVo.setRecharge(recharge);
            } else {
                for (MallOrderGoods mallOrderGoods : rechargeList) {
                    recharge.add(mallOrderGoods.getPayPrice());
                }
                accountMyTeamVo.setRecharge(recharge);
            }
            return accountMyTeamVo;
        }).collect(Collectors.toList());

        AppMyTeamInfoVO appMyTeamInfoVo = new AppMyTeamInfoVO();
        appMyTeamInfoVo.setList(collect);
        appMyTeamInfoVo.setList2(collect2);
        appMyTeamInfoVo.setDirectReferrer(list.size());
        List<MallUser> mallUsers = queryMyTeam(loginUser.getAccountLogin().getUuid());
        appMyTeamInfoVo.setAll(mallUsers.size());

        appMyTeamInfoVo.setTodayPerformance(mallUser.getAccruedIncome());
        appMyTeamInfoVo.setWaitPerformance(mallUser.getWaitIncome());

        appMyTeamInfoVo.setLimit(limit);
        return appMyTeamInfoVo;
    }

    @Override
    public int editMallUser(MallUser mallUser) {
        MallUser user = lambdaQuery().eq(MallUser::getId, mallUser.getId()).one();
        //换绑手机号
        IAccountLoginCheckService accountLoginCheckService = SpringUtil.getBean(IAccountLoginCheckService.class);
        if (!user.getMobile().equals(mallUser.getMobile())) {
            // 查询是否已经存在
            AccountLoginCheck one = accountLoginCheckService.lambdaQuery().eq(AccountLoginCheck::getPhone, mallUser.getMobile()).one();
            if (one != null) {
                throw new CustomException("该手机号已存在");
            }
            UpdateNewPhoneDTO updateNewPhoneDTO = new UpdateNewPhoneDTO();
            updateNewPhoneDTO.setOldPhone(user.getMobile());
            updateNewPhoneDTO.setNewPhone(mallUser.getMobile());
            accountLoginCheckService.updatePhone(updateNewPhoneDTO, user.getUuid());
        }
        if (StringUtils.isNotBlank(mallUser.getPassword())) {
            //修改登录信息 将密码加密
            String hash = Md5Utils.hash(mallUser.getPassword());
            AccountLoginCheck one = accountLoginCheckService.lambdaQuery().eq(AccountLoginCheck::getPhone, mallUser.getMobile()).one();
            one.setPassword(hash);
            accountLoginCheckService.updateById(one);
            mallUser.setPassword(hash);
        }
        return updateMallUser(mallUser);
    }

    @Override
    public MallUserStaticsVo queryUserStatistics() {
        MallUserStaticsVo mallUserStaticsVo = new MallUserStaticsVo();
        // 获取今天的时间
        LocalDateTime beginOfDay = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
        String Day = DateUtil.format(beginOfDay, "yyyyMMdd");
        // 用户总数
        Integer totalCount = lambdaQuery().count();
        // 昨日新增用户数
        Integer lastTotalCount = lambdaQuery().apply("date_format(create_time,'%Y%m%d') = " + "'" + Day + "'").count();

 /*       // 普通用户数
        Integer userCount = lambdaQuery().eq(MallUser::getUserLevel, UserType.ORDINARY).count();
        // 昨日新增普通用户数
        Integer lastUserCount = lambdaQuery().eq(MallUser::getUserLevel, UserType.ORDINARY).apply("date_format(create_time,'%Y%m%d') = " + "'" + Day + "'").count();
    // 会员数
        Integer vipCount = lambdaQuery().eq(MallUser::getUserLevel, UserType.INTERMEDIATE_MEMBER).count();
        // 昨日开通会员数
//        Integer lastVipCount = mallOrderMapper.getCount(Day);
        Integer lastVipCount = lambdaQuery().eq(MallUser::getUserLevel, UserType.INTERMEDIATE_MEMBER).apply("date_format(start_svip_time,'%Y%m%d') = " + "'" + Day + "'").count();
*/

        // 禁用用户数
        Integer disableCount = lambdaQuery().eq(MallUser::getStatus, 1).count();
        // 昨日禁用用户数
        Integer lastDisableCount = lambdaQuery().eq(MallUser::getStatus, 1).apply("date_format(update_time,'%Y%m%d') = " + "'" + Day + "'").count();

        mallUserStaticsVo.setDisableCount(disableCount != null ? disableCount : 0);
        mallUserStaticsVo.setLastDisableCount(lastDisableCount != null ? lastDisableCount : 0);
        /*mallUserStaticsVo.setVipCount(vipCount != null ? vipCount : 0);
        mallUserStaticsVo.setLastVipCount(lastVipCount != null ? lastVipCount : 0);
        mallUserStaticsVo.setUserCount(userCount != null ? userCount : 0);
        mallUserStaticsVo.setLastUserCount(lastUserCount != null ? lastUserCount : 0);*/
        mallUserStaticsVo.setTotalCount(totalCount != null ? totalCount : 0);
        mallUserStaticsVo.setLastTotalCount(lastTotalCount != null ? lastTotalCount : 0);

        return mallUserStaticsVo;
    }

    @Override
    public List<MallUser> selectOneByUuidDown(Long upUuid) {
        return mallUserMapper.selectOneByUuidDown(upUuid);
    }

    @Override
    public Long selectApprovalStatus(Long uuid) {
        return mallUserMapper.selectApprovalStatus(uuid);
    }

    @Override
    public Long selectStoreApprovalStatus(Long uuid) {
        return mallUserMapper.selectStoreApprovalStatus(uuid);
    }


    @Override
    public BigDecimal waitGoodsRoll() {
        return baseMapper.waitGoodsRoll();
    }

    @Override
    public BigDecimal goodsRoll() {
        return baseMapper.goodsRoll();
    }


    @Override
    public Page<AccountMyTeamVo> appSelectOneTeam(ReqPageParam param, Long uuid) {

        Page<AccountMyTeamVo> page = new Page<>(param.getPageNum(), param.getPageSize());
        Page<AccountMyTeamVo> pageOne = null;

        if (param.getTeamType() == 1) {
            //一级分页
            pageOne = baseMapper.appSelectOneTeam(page, uuid);
            if (pageOne != null && !pageOne.getRecords().isEmpty()) {
                pageOne.getRecords().forEach(item -> {
                    Integer orderCount = mallOrderGoodsService.lambdaQuery().eq(MallOrderGoods::getUuid, item.getUuid()).in(MallOrderGoods::getOrderStatus, OrderStatus.DAI_CENTXT, OrderStatus.OK).notIn(MallOrderGoods::getAftersaleStatus, AfterSaleStatus.DEL_PAY).count();
                    Integer count = lambdaQuery().eq(MallUser::getReferrerUuid, item.getUuid()).count();
                    item.setOrderCount(orderCount);
                    item.setRecommendedNumber(count);

                    BigDecimal recharge = BigDecimal.ZERO;
                    List<MallOrderGoods> rechargeList = mallOrderGoodsService.lambdaQuery().eq(MallOrderGoods::getUuid, item.getUuid()).eq(MallOrderGoods::getOrderType, OrderType.RECHARGE).list();
                    if (rechargeList.isEmpty()) {
                        item.setRecharge(recharge);
                    } else {
                        for (MallOrderGoods mallOrderGoods : rechargeList) {
                            recharge = recharge.add(mallOrderGoods.getPayPrice());
                        }
                        item.setRecharge(recharge);
                    }
                });
            }
        }

        if (param.getTeamType() == 2) {
            //二级分页
            pageOne = baseMapper.appSelectTwoTeam(page, uuid);
            if (pageOne != null && !pageOne.getRecords().isEmpty()) {
                pageOne.getRecords().forEach(item -> {
                    Integer orderCount = mallOrderGoodsService.lambdaQuery().eq(MallOrderGoods::getUuid, item.getUuid()).in(MallOrderGoods::getOrderStatus, OrderStatus.DAI_CENTXT, OrderStatus.OK).notIn(MallOrderGoods::getAftersaleStatus, AfterSaleStatus.DEL_PAY).count();
                    Integer count = lambdaQuery().eq(MallUser::getReferrerUuid, item.getUuid()).count();
                    item.setOrderCount(orderCount);
                    item.setRecommendedNumber(count);

                    BigDecimal recharge = BigDecimal.ZERO;
                    List<MallOrderGoods> rechargeList = mallOrderGoodsService.lambdaQuery().eq(MallOrderGoods::getUuid, item.getUuid()).eq(MallOrderGoods::getOrderType, OrderType.RECHARGE).list();
                    if (rechargeList.isEmpty()) {
                        item.setRecharge(recharge);
                    } else {
                        for (MallOrderGoods mallOrderGoods : rechargeList) {
                            recharge = recharge.add(mallOrderGoods.getPayPrice());
                        }
                        item.setRecharge(recharge);
                    }
                });

            }
        }
        return pageOne;
    }
}
